package com.yt.common.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

/**
 * @Description ：精准的加减乘除
 * @Author ： 解风
 * @Date ： 2018/01/02 15:40
 */
public class BigDecimalUtils {

    /**
     * 默认保留位：2
     */
    private static final int DEFAULT_SCALE = 2;
    private static final int SCALE_8 = 8;

    /**
     * 默认四舍五入规则为：向上舍入
     */
    private static final int ROUND_HALF_UP = BigDecimal.ROUND_HALF_UP;

    /**
     * 默认四舍五入规则为：向下舍入
     */
    private static final int ROUND_HALF_DOWN = BigDecimal.ROUND_HALF_DOWN;

    /**
     * 默认四舍五入规则为：直接删除多余 如：2.58-2.5
     */
    private static final int ROUND_DOWN = BigDecimal.ROUND_DOWN;

    /**
     * 默认四舍五入规则为：进位处理 如：2.12-2.2
     */
    private static final int ROUND_UP = BigDecimal.ROUND_UP;

    /**
     * 获取BigDecimal
     *
     * @param value
     * @param scale
     * @return
     */
    public static BigDecimal getBigDecimal(Object value, Integer scale) {
        if (null == scale) {
            scale = DEFAULT_SCALE;
        }
        if (null == value) {
            return new BigDecimal("0.00");
        }
        BigDecimal big = getBigDecimalObject(value);
        BigDecimal dec = big.setScale(scale, RoundingMode.HALF_UP);
        return dec;
    }

    /**
     * 获取BigDecimal 保留两位小数
     *
     * @param value
     * @return
     */
    public static BigDecimal getBigDecimal(Object value) {
        return getBigDecimal(value, DEFAULT_SCALE);
    }

    /**
     * 转换Double
     *
     * @param value
     * @param scale
     * @return
     */
    public static Double toDouble(Object value, Integer scale) {
        BigDecimal d = getBigDecimal(value, scale);
        return d.doubleValue();
    }

    /**
     * 转换Double 保留两位小数
     *
     * @param value
     * @return
     */
    public static Double toDouble(Object value) {
        return toDouble(value, DEFAULT_SCALE);
    }

    /**
     * 转换Double
     *
     * @param value 值
     * @param scale 保留小数
     * @return
     */
    public static Integer toInteger(Object value, Integer scale) {
        BigDecimal d = getBigDecimal(value, scale);
        return d.intValue();
    }

    /**
     * 转换Double 保留两位小数
     *
     * @param value
     * @return
     */
    public static Integer toInteger(Object value) {
        return toInteger(value, DEFAULT_SCALE);
    }

    /**
     * 转换Long
     *
     * @param value
     * @param scale
     * @return
     */
    public static Long toLong(Object value, Integer scale) {
        BigDecimal d = getBigDecimal(value, scale);
        return d.longValue();
    }

    /**
     * 转换Long 保留两位小数
     *
     * @param value
     * @return
     */
    public static Long toLong(Object value) {
        return toLong(value, DEFAULT_SCALE);
    }

    /**
     * 转换String
     *
     * @param value
     * @param scale
     * @return
     */
    public static String toString(Object value, Integer scale) {
        BigDecimal d = getBigDecimal(value, scale);
        return d.toString();
    }

    /**
     * 转换String 保留两位小数
     *
     * @param value
     * @return
     */
    public static String toString(Object value) {
        return toString(value, DEFAULT_SCALE);
    }

    /**
     * 转换String 去掉科学技术法
     *
     * @param value
     * @param scale
     * @return
     */
    public static String toPlainString(Object value, Integer scale) {
        BigDecimal d = getBigDecimal(value, scale);
        return d.toPlainString();
    }

    /**
     * 转换String 保留两位小数 去掉科学技术法
     *
     * @param value
     * @return
     */
    public static String toPlainString(Object value) {
        return toPlainString(value, DEFAULT_SCALE);
    }

    /**
     * 加法运算
     *
     * @param v1 加数
     * @param v2 被加数
     * @return
     */
    public static BigDecimal add(Object v1, Object v2, Integer scale) {
        BigDecimal b1 = getBigDecimal(v1, scale);
        BigDecimal b2 = getBigDecimal(v2, scale);
        return b1.add(b2).setScale(scale, RoundingMode.HALF_UP);
    }

    public static BigDecimal add(Object v1, Object v2) {
        return add(v1, v2, DEFAULT_SCALE);
    }

    /**
     * 减法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static BigDecimal sub(Object v1, Object v2, Integer scale) {
        BigDecimal b1 = getBigDecimal(v1, scale);
        BigDecimal b2 = getBigDecimal(v2, scale);
        return b1.subtract(b2).setScale(scale, RoundingMode.HALF_UP);
    }

    public static BigDecimal sub(Object v1, Object v2) {
        return sub(v1, v2, DEFAULT_SCALE);
    }

    /**
     * 乘法  toPlainString() 去掉科学技术法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static BigDecimal multiply(Object v1, Object v2, Integer scale) {
        BigDecimal b1 = getBigDecimal(v1, scale);
        BigDecimal b2 = getBigDecimal(v2, scale);
        return b1.multiply(b2).setScale(scale, RoundingMode.HALF_UP);
    }

    public static BigDecimal multiply(Object v1, Object v2) {
        return multiply(v1, v2, DEFAULT_SCALE);
    }

    /**
     * 乘法  toPlainString() 去掉科学技术法
     *
     * @param v1
     * @param v2
     * @return
     */
    public static String multiplyStr(Object v1, Object v2, Integer scale) {
        return multiply(v1, v2, scale).toPlainString();
    }

    public static String multiplyStr(Object v1, Object v2) {
        return multiplyStr(v1, v2, DEFAULT_SCALE);
    }


    /**
     * 除法运算<br>
     * 当发生除不尽的情况时，由scale参数指定精度，以后的数字四舍五入。
     *
     * @param v1    除数
     * @param v2    被除数
     * @param scale 精确精度
     * @return
     */
    public static BigDecimal divide(Object v1, Object v2, Integer scale) {
        BigDecimal b1 = getBigDecimal(v1, scale);
        BigDecimal b2 = getBigDecimal(v2, scale);
        return b1.divide(b2, scale);
    }

    public static BigDecimal divide(Object v1, Object v2) {
        return divide(v1, v2, DEFAULT_SCALE);
    }

    /**
     * 比较两个数<br>
     * v1 > v2 return 1<br>
     * v1 = v2 return 0<br>
     * v1 < v2 return -1
     *
     * @param v1 比较数
     * @param v2 被比较数
     * @return
     */
    public static int compareTo(Object v1, Object v2, Integer scale) {
        BigDecimal b1 = getBigDecimal(v1, scale);
        BigDecimal b2 = getBigDecimal(v2, scale);
        return b1.compareTo(b2);
    }

    public static int compareTo(Object v1, Object v2) {
        return compareTo(v1, v2, DEFAULT_SCALE);
    }

    /**
     * 返回较小数
     *
     * @param v1
     * @param v2
     * @return
     */
    public static BigDecimal compareToMin(Object v1, Object v2, Integer scale) {
        BigDecimal b1 = getBigDecimal(v1, scale);
        BigDecimal b2 = getBigDecimal(v2, scale);
        return b1.min(b2);
    }

    /**
     * 返回较大数
     *
     * @param v1
     * @param v2
     * @return
     */
    public static BigDecimal compareToMax(Object v1, Object v2, Integer scale) {
        BigDecimal b1 = getBigDecimal(v1, scale);
        BigDecimal b2 = getBigDecimal(v2, scale);
        return b1.max(b2);
    }

    /**
     * 返回金额 格式为 2.00的字符串
     *
     * @param v1
     * @return
     */
    public static String interceptLastFourAmount(Object v1) {
        DecimalFormat df = new DecimalFormat("#.00");
        String temp = df.format(v1);
        if (Double.valueOf(temp) >= (double) 10) {
            return temp.substring(temp.length() - 4);
        } else {
            return temp;
        }

    }

    /**
     * 将object转换为Bigdecimal
     *
     * @param value 待转换的数值
     * @return
     */
    public static BigDecimal getBigDecimalObject(Object value) {

        BigDecimal resultValue = new BigDecimal(0);
        if (null == value) {
            return resultValue;
        }
        if (value instanceof String) {
            if ("".equals(value)) {
                return resultValue;
            }
            resultValue = new BigDecimal((String) value);
        } else if (value instanceof Integer) {
            resultValue = new BigDecimal((Integer) value);
        } else if (value instanceof Long) {
            resultValue = new BigDecimal((Long) value);
        } else if (value instanceof Double) {
            resultValue = BigDecimal.valueOf((Double) value);
        } else if (value instanceof BigDecimal) {
            resultValue = (BigDecimal) value;
        }

        return resultValue;
    }

    public static void main(String[] args) {
//		BigDecimal dec = new BigDecimal(1231232131231231231.123456);
//		System.out.println(dec.setScale(4, BigDecimal.ROUND_HALF_UP));
        BigDecimal b1 = getBigDecimal(10, 2);
        BigDecimal b2 = getBigDecimal(3, 2);
        System.out.println(b1 + "---" + b2);

        System.out.println(b1.divide(b2, RoundingMode.CEILING));
        System.out.println(b1.divide(new BigDecimal(3), 2, RoundingMode.HALF_UP));
//		System.out.println(multiply(40000, 0.0019));
    }
}
